package com.zdp.sources.common.db;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.util.Objects;

/**
 * @author sesshomaru
 * @date 2022/2/28
 */
@Component
@Aspect
@Order(-100)
public class DataSourceSwitchAspect {

    private final Logger logger = LoggerFactory.getLogger(DataSourceSwitchAspect.class);

    /**
     * <h2>根据注解切换数据源</h2>
     */
    @Pointcut("@annotation(com.zdp.sources.common.db.DataSourceSwitch)")
    public void annotationPointcut() {}

    /**
     * <h2>定义只读切点</h2>
     */
    @Pointcut("!@annotation(com.zdp.sources.common.db.DataSourceSwitch) && execution(* com.zdp.sources.service.impl..*.select*(..)) " +
            "|| execution(* com.zdp.sources.service.impl..*.get*(..))")
    public void readPointcut() {}

    /**
     * <h2>定义只写切点</h2>
     */
    @Pointcut("!@annotation(com.zdp.sources.common.db.DataSourceSwitch) && execution(* com.zdp.sources.service.impl..*.insert*(..)) " +
            "|| execution(* com.zdp.sources.service.impl..*.delete*(..))")
    public void writePointcut() {}

    @Before("readPointcut()")
    public void read() {
        DBContextHolder.slave();
    }

    @Before("writePointcut()")
    public void write() {
        DBContextHolder.master();
    }

    @Before("annotationPointcut()")
    public void annotation(JoinPoint joinPoint) {
        logger.info("根据注解切换数据源 ...");
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        DataSourceSwitch dataSourceSwitch = methodSignature.getMethod().getAnnotation(DataSourceSwitch.class);
        // 默认操作主库
        if (Objects.isNull(dataSourceSwitch) || Objects.isNull(dataSourceSwitch.value())) {
            DBContextHolder.master();
        } else {
            DBContextHolder.set(dataSourceSwitch.value());
            logger.info("切换到[{}] ...", dataSourceSwitch.value());
        }
    }
}
